import types
import typing
from datetime import datetime
from typing import TypedDict

from arq import Worker as W, ArqRedis
from arq.connections import RedisSettings, create_pool
from arq.cron import CronJob, cron
from arq.typing import OptionType, WeekdayOptionType, SecondsTimedelta
from arq.worker import Function


class BaseCTX(TypedDict):
    redis: ArqRedis


class CTX(BaseCTX):
    job_id: str
    job_try: int
    enqueue_time: datetime


class Worker(W):
    functions: typing.List[Function | types.CoroutineType] = []
    cron_jobs: typing.List[CronJob] = []

    def __init__(self, *,redisSettings:RedisSettings, **kwargs):
        self.__dict__.update(kwargs)
        self.redisSettings = redisSettings
        if self.functions or self.cron_jobs:
            super().__init__(
                functions=self.functions or [],
                cron_jobs=self.cron_jobs or None,
                on_startup=self.startup,
                on_shutdown=self.shutdown,
                on_job_start=self.on_job_start,
                on_job_end=self.on_job_end,
                redis_settings=redisSettings,
                # keep_result=configs.WORKER_KEEP
            )

    def sync_run(self):
        self.run()

    async def async_run(self):
       await self.async_run()


    @classmethod
    async def create_pool(cls,redisSettings:RedisSettings):
        return await create_pool(redisSettings)

    @staticmethod
    async def startup(ctx: BaseCTX):
        print("启动了运行了！！！！")

    @staticmethod
    async def shutdown(ctx: BaseCTX):
        pass

    @staticmethod
    async def on_job_start(ctx: BaseCTX):
        pass

    @staticmethod
    async def on_job_end(ctx: BaseCTX):
        pass

    @classmethod
    def task(cls, func):
        # 任务开始注册了！
        print("任务开始注册了！",f'register task:{func.__name__}')
        cls.functions.append(func)

    @classmethod
    def cron(cls,
             name: typing.Optional[str] = None,
             month: OptionType = None,
             day: OptionType = None,
             weekday: WeekdayOptionType = None,
             hour: OptionType = None,
             minute: OptionType = None,
             second: OptionType = 0,
             microsecond: int = 123_456,
             run_at_startup: bool = False,
             unique: bool = True,
             timeout: typing.Optional[SecondsTimedelta] = None,
             keep_result: typing.Optional[float] = 0,
             keep_result_forever: typing.Optional[bool] = False,
             max_tries: typing.Optional[int] = 1):
        """ 最低1分钟1次 """

        def wrapper(func):
            print("register worker了！", f'register worker:{func.__name__}')
            cls.cron_jobs.append(
                cron(func, name=name, month=month, day=day, weekday=weekday, hour=hour, minute=minute,
                     second=second, microsecond=microsecond, run_at_startup=run_at_startup, unique=unique,
                     timeout=timeout, keep_result=keep_result, keep_result_forever=keep_result_forever,
                     max_tries=max_tries)
            )

        return wrapper


if __name__ == '__main__':
    Worker()
